/**
 @file sys_usw_mac_stats.c

 @date 2009-12-22

 @version v2.0

*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "ctc_error.h"
#include "ctc_macro.h"
#include "ctc_stats.h"
#include "ctc_hash.h"
#include "sys_usw_common.h"
#include "sys_usw_stats.h"
#include "sys_usw_ftm.h"
#include "sys_usw_chip.h"
#include "sys_usw_opf.h"
#include "sys_usw_port_api.h"
#include "sys_usw_qos_api.h"
#include "sys_usw_l3if.h"
#include "sys_usw_dma.h"
#include "sys_usw_interrupt.h"
#include "sys_usw_vlan.h"
#include "sys_usw_register.h"
#include "sys_usw_wb_common.h"
#include "drv_api.h"
#include "usw/include/drv_common.h"
#include "sys_usw_mac.h"
#include "sys_usw_dmps_db.h"
#include "sys_usw_port_api.h"

/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/
sys_mac_stats_master_t* usw_mac_stats_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};

#define ___________MAC_STATS_COMMON___________

#define SYS_STATS_INIT_CHECK() \
    do { \
        LCHIP_CHECK(lchip); \
        if (usw_mac_stats_master[lchip] == NULL){ \
            SYS_STATS_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Feature not initialized \n");\
			return CTC_E_NOT_INIT; \
        } \
    } while (0)

#define STATS_LOCK() \
    do { \
        if (usw_mac_stats_master[lchip]->p_stats_mutex) sal_mutex_lock(usw_mac_stats_master[lchip]->p_stats_mutex); \
    } while (0)

#define STATS_UNLOCK() \
    do { \
        if (usw_mac_stats_master[lchip]->p_stats_mutex) sal_mutex_unlock(usw_mac_stats_master[lchip]->p_stats_mutex); \
    } while (0)

#define CTC_ERROR_RETURN_UNLOCK(op) \
    do { \
        int32 rv; \
        if ((rv = (op)) < 0) \
        { \
            sal_mutex_unlock(usw_mac_stats_master[lchip]->p_stats_mutex); \
            return (rv); \
        } \
    } while (0)

#define RX_TYPE(_TYPE_) (_TYPE_)
#define TX_TYPE(_TYPE_) (_TYPE_ - SYS_STATS_MAC_SEND_UCAST)
#define SYS_USW_400G_MAC_ID_OFFSET 4

#define SYS_MAC_STATS_GET_RAM_NUM(lchip, ram_num, speed_mode, if_type) \
    do {\
        if (CTC_PORT_SPEED_800G == speed_mode)\
        {\
            ram_num = 8;\
        }\
        else if (CTC_PORT_SPEED_400G == speed_mode)\
        {\
            ram_num = (if_type == CTC_PORT_IF_CR8)? 8 : 4;\
        }\
        else if (CTC_PORT_SPEED_200G == speed_mode)\
        {\
            ram_num = DRV_FROM_AT(lchip)? 2 : 1;\
        }\
        else\
        {\
            ram_num = 1;\
        }\
    } while (0)

#define SYS_MAC_STATS_GET_TABLE_RANGE(lchip, start_tbl, end_tbl)\
    do {\
        if (DRV_FROM_AT(lchip))\
        {\
            start_tbl = McMacStats0Cfg_t;\
            end_tbl = McMacStats1Cfg_t;\
        }\
        else if (DRV_IS_TMG(lchip))\
        {\
            start_tbl = QuadSgmacStatsCfg_t;\
            end_tbl = QuadSgmacStatsCfg_t;\
        }\
        else if (DRV_FROM_TMM(lchip))\
        {\
            start_tbl = McMacStats0Cfg_t;\
            end_tbl = McMacStats9Cfg_t;\
        }\
        else if (DRV_IS_DUET2(lchip))\
        {\
            start_tbl = QuadSgmacStatsCfg0_t;\
            end_tbl = QuadSgmacStatsCfg15_t;\
        }\
        else\
        {\
            start_tbl = QuadSgmacStatsCfg0_t;\
            end_tbl = QuadSgmacStatsCfg17_t;\
        }\
    }while(0)

#define SYS_MAC_STATS_GET_INSTANCE_NUM(lchip, instance)\
    do {\
        if (DRV_FROM_AT(lchip))\
        {\
            instance = 20;\
        }\
        else if (DRV_IS_TMG(lchip))\
        {\
            instance = 20;\
        }\
        else if (DRV_FROM_TMM(lchip))\
        {\
            instance = 8;\
        }\
        else\
        {\
            instance = 1;\
        }\
    }while(0)\

extern int32 sys_usw_tsx_mac_stats_check(uint8 lchip);
/***************************************************************
 *
 * Function
 *
 ***************************************************************/

#define ___________MAC_STATS_FUNCTION________________________


#if defined(ARCTIC)
uint32
_sys_at_mac_stats_get_block_id(uint8 lchip, uint32 tbl_id, uint16 tbl_base)
{
    uint32 block_id = 0;
    uint32 ram_id = 0;
    uint32 core_id = (SYS_CORE_PP_BASE(lchip) == SYS_PP_BASE(lchip)) ? 0 : 1;
    if (tbl_id == McMacStatsRam0_t)
    {
        ram_id = 0;
    }
    else if (tbl_id == McMacStatsRam1_t)
    {
        ram_id = 1;
    }
    else if (tbl_id == QuadSgmacStatsRam_t)
    {
        ram_id = 2;
    }
    block_id = tbl_base + (ram_id << 16) + (core_id << 18);
    return block_id;
}
/*get rx or tx stats*/
int32
_sys_at_mac_stats_get_mac_stats(uint8 lchip, uint32 tbl_id, uint16 tbl_base, uint8 dir, void* p_mac_stats)
{
    uint32 block_id = 0;
    sys_mac_stats_rx_t* p_stats_rx = NULL;
    sys_mac_stats_tx_t* p_stats_tx = NULL;
    sys_usw_dmps_mac_stats_t mac_stats;

    sal_memset(&mac_stats,0,sizeof(sys_usw_dmps_mac_stats_t));
    
    SYS_STATS_DBG_FUNC();
    block_id = _sys_at_mac_stats_get_block_id(lchip, tbl_id, tbl_base);
    CTC_ERROR_RETURN(sys_usw_port_api_get_mac_stats(lchip, block_id, &mac_stats));

    if (dir == CTC_STATS_MAC_STATS_RX)
    {
        p_stats_rx = (sys_mac_stats_rx_t*)p_mac_stats;
        sal_memcpy(p_stats_rx->mac_stats_rx_bytes,mac_stats.rx_bytes,sizeof(uint64)*SYS_STATS_MAC_RCV_NUM);
        sal_memcpy(p_stats_rx->mac_stats_rx_pkts,mac_stats.rx_pkts,sizeof(uint64)*SYS_STATS_MAC_RCV_NUM);
    }
    else
    {
        p_stats_tx = (sys_mac_stats_tx_t*)p_mac_stats;
        sal_memcpy(p_stats_tx->mac_stats_tx_bytes,mac_stats.tx_bytes,sizeof(uint64)*SYS_STATS_MAC_SEND_NUM);
        sal_memcpy(p_stats_tx->mac_stats_tx_pkts,mac_stats.tx_pkts,sizeof(uint64)*SYS_STATS_MAC_SEND_NUM);
    }
    
    return CTC_E_NONE;
}
/*clear rx or tx stats*/
int32
_sys_at_mac_stats_clear_mac_stats(uint8 lchip, uint32 tbl_id, uint16 tbl_base, uint8 dir)
{
    uint32 block_id = 0;
    SYS_STATS_DBG_FUNC();
    block_id = _sys_at_mac_stats_get_block_id(lchip, tbl_id, tbl_base);

    CTC_ERROR_RETURN(sys_usw_port_api_clear_mac_stats(lchip, block_id, dir));
    
    return CTC_E_NONE;
}
int32 
_sys_at_mac_stats_sync_throughput(uint8 lchip, uint32 lport, uint32 tbl_id, uint16 tbl_base, uint32 mac_ipg)
{
    uint32 block_id = 0;
    sys_usw_dmps_mac_stats_t mac_stats;
    uint8  stats_type = 0;
    ctc_stats_basic_t stats_tx_basic;
    ctc_stats_basic_t stats_rx_basic;

    sal_memset(&mac_stats, 0, sizeof(sys_usw_dmps_mac_stats_t));
    sal_memset(&stats_tx_basic, 0, sizeof(ctc_stats_basic_t));
    sal_memset(&stats_rx_basic, 0, sizeof(ctc_stats_basic_t));
    SYS_STATS_DBG_FUNC();

    block_id = _sys_at_mac_stats_get_block_id(lchip, tbl_id, tbl_base);

    CTC_ERROR_RETURN(sys_usw_port_api_get_mac_stats(lchip, block_id, &mac_stats));

    for (stats_type = SYS_STATS_MAC_RCV_GOOD_UCAST; stats_type < SYS_STATS_MAC_STATS_TYPE_NUM; stats_type++)
    {
        if (!((SYS_STATS_MAC_RCV_GOOD_UCAST == stats_type) || (SYS_STATS_MAC_RCV_GOOD_MCAST == stats_type)
            || (SYS_STATS_MAC_RCV_GOOD_BCAST == stats_type) || (SYS_STATS_MAC_SEND_UCAST == stats_type)
        || (SYS_STATS_MAC_SEND_MCAST == stats_type) || (SYS_STATS_MAC_SEND_BCAST == stats_type)))
        {
            continue;
        }
        if (stats_type < SYS_STATS_MAC_RCV_NUM)
        {
            stats_rx_basic.packet_count = mac_stats.rx_pkts[RX_TYPE(stats_type)];
            stats_rx_basic.byte_count = mac_stats.rx_bytes[RX_TYPE(stats_type)];
            usw_mac_stats_master[lchip]->mac_throughput.bytes[lport][CTC_STATS_MAC_STATS_RX] += (stats_rx_basic.byte_count + stats_rx_basic.packet_count*(8 + mac_ipg));
        }
        else
        {
            stats_tx_basic.packet_count = mac_stats.tx_pkts[TX_TYPE(stats_type)];
            stats_tx_basic.byte_count = mac_stats.tx_bytes[TX_TYPE(stats_type)];
            usw_mac_stats_master[lchip]->mac_throughput.bytes[lport][CTC_STATS_MAC_STATS_TX] += (stats_tx_basic.byte_count + stats_tx_basic.packet_count*(8 + mac_ipg));
        }
    }

    return CTC_E_NONE;
}

#endif
STATIC int32
_sys_usw_mac_stats_get_property_field(uint8 lchip, uint32 port_type, sys_mac_stats_property_t property, uint32* p_filed_id)
{
    switch (property)
    {
    case SYS_MAC_STATS_PROPERTY_CLEAR:
        *p_filed_id = DRV_FROM_TMM(lchip) ? (((port_type != SYS_DMPS_CPUMAC_NETWORK_PORT)&&!DRV_IS_TMG(lchip))? McMacStats0Cfg_cfgClearOnRead0_f:QuadSgmacStatsCfg_clearOnRead_f): QuadSgmacStatsCfg0_clearOnRead_f;
        break;

    case SYS_MAC_STATS_PROPERTY_HOLD:
        *p_filed_id = DRV_FROM_TMM(lchip) ? (((port_type != SYS_DMPS_CPUMAC_NETWORK_PORT)&&!DRV_IS_TMG(lchip))? McMacStats0Cfg_cfgIncrHold0_f:QuadSgmacStatsCfg_incrHold_f) : QuadSgmacStatsCfg0_incrHold_f;
        break;

    case SYS_MAC_STATS_PROPERTY_SATURATE:
        *p_filed_id = DRV_FROM_TMM(lchip) ? (((port_type != SYS_DMPS_CPUMAC_NETWORK_PORT)&&!DRV_IS_TMG(lchip))?McMacStats0Cfg_cfgIncrSaturate0_f:QuadSgmacStatsCfg_incrSaturate_f) : QuadSgmacStatsCfg0_incrSaturate_f;
        break;

    case SYS_MAC_STATS_PROPERTY_MTU1:
        *p_filed_id = DRV_FROM_TMM(lchip) ? (((port_type != SYS_DMPS_CPUMAC_NETWORK_PORT)&&!DRV_IS_TMG(lchip))?McMacStats0Cfg_cfgQuadSgmac0PacketLenMtu1_f:QuadSgmacStatsCfg_packetLenMtu1_f) : QuadSgmacStatsCfg0_packetLenMtu1_f;
        break;

    case SYS_MAC_STATS_PROPERTY_MTU2:
        *p_filed_id = DRV_FROM_TMM(lchip) ? (((port_type != SYS_DMPS_CPUMAC_NETWORK_PORT)&&!DRV_IS_TMG(lchip))?McMacStats0Cfg_cfgQuadSgmac0PacketLenMtu2_f:QuadSgmacStatsCfg_packetLenMtu2_f) : QuadSgmacStatsCfg0_packetLenMtu2_f;
        break;

    case SYS_MAC_STATS_PROPERTY_PFC:
        *p_filed_id = DRV_FROM_TMM(lchip) ? (((port_type != SYS_DMPS_CPUMAC_NETWORK_PORT)&&!DRV_IS_TMG(lchip))?McMacStats0Cfg_cfgPfcPriStatsEnable0_f:QuadSgmacStatsCfg_pfcPriStatsEnable_f) : QuadSgmacStatsCfg0_pfcPriStatsEnable_f;
        break;

    default:
        return CTC_E_INVALID_PARAM;

    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mac_stats_get_property_table(uint8 lchip, uint32 port_type, uint32 mac_id, uint32* p_tbl_id, uint32* p_index)
{
    if(DRV_FROM_AT(lchip))
    {
        *p_tbl_id = (port_type != SYS_DMPS_CPUMAC_NETWORK_PORT) ? ((mac_id & 0x7) <= 3 ? McMacStats0Cfg_t : McMacStats1Cfg_t) : QuadSgmacStatsCfg_t;
        *p_index = (port_type != SYS_DMPS_CPUMAC_NETWORK_PORT) ? ((mac_id % 160) >> 3) : 0;
    }
    else if(DRV_IS_TMG(lchip))
    {
        *p_tbl_id = QuadSgmacStatsCfg_t;
        *p_index = mac_id/4;
    }
    else if(DRV_FROM_TMM(lchip))
    {
        *p_tbl_id = (port_type != SYS_DMPS_CPUMAC_NETWORK_PORT)?McMacStats0Cfg_t + (((mac_id%40) >> 2)&0x1F):QuadSgmacStatsCfg_t;
        *p_index = (port_type != SYS_DMPS_CPUMAC_NETWORK_PORT)?mac_id/40:0;
    }
    else
    {
        *p_tbl_id = QuadSgmacStatsCfg0_t + ((mac_id >> 2)&0x1F);
        *p_index = 0;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mac_stats_set_global_property(uint8 lchip, sys_mac_stats_property_t property, uint32 value)
{
    uint32 tbl_id = 0;
    uint32 field_id = 0;
    uint32 cmd = 0;
    uint32 start_tbl;
    uint32 end_tbl;
    uint8 instance=0;
    uint8 i = 0;

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property_field(lchip, SYS_DMPS_NETWORK_PORT, property, &field_id));

    SYS_MAC_STATS_GET_TABLE_RANGE(lchip, start_tbl, end_tbl);
    SYS_MAC_STATS_GET_INSTANCE_NUM(lchip, instance);
    for (tbl_id = start_tbl; tbl_id <= end_tbl; tbl_id++)
    {
        for(i = 0; i < instance; i++)
        {
            cmd = DRV_IOW(tbl_id, field_id);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, i, DRV_CMD_PP_EN(cmd), &value));
        }
    }

    /*cpumac network port use QuadSgmacStatsCfg*/
    if (DRV_FROM_TMM(lchip))
    {
        i = (DRV_IS_TMG(lchip)?20:0);
        CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property_field(lchip, SYS_DMPS_CPUMAC_NETWORK_PORT, property, &field_id));
        cmd = DRV_IOW(QuadSgmacStatsCfg_t, field_id);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, i, cmd, &value));
    }
    return CTC_E_NONE;
}

int32
_sys_usw_mac_stats_get_global_property(uint8 lchip, sys_mac_stats_property_t property, uint32* p_value)
{
    uint32 tbl_id = DRV_IS_TMG(lchip)?QuadSgmacStatsCfg_t:(DRV_FROM_TMM(lchip) ? McMacStats0Cfg_t : QuadSgmacStatsCfg0_t);
    uint32 field_id = 0;
    uint32 cmd = 0;

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property_field(lchip, SYS_DMPS_NETWORK_PORT, property, &field_id));

    cmd = DRV_IOR(tbl_id, field_id);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, p_value));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mac_stats_set_property(uint8 lchip, uint32 gport, sys_mac_stats_property_t property, uint32 value)
{
    uint16 lport = 0;
    uint32 tbl_id = 0;
    uint32 field_id = 0;
    uint32 cmd = 0;
    uint8 mac_num = 0;
    uint32 speed_mode = 0;
    uint32 index = 0;
    uint32 port_type = 0;
    uint32 mac_id = 0;
    uint32 if_type = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);
    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    if ((port_type != SYS_DMPS_NETWORK_PORT)&&(port_type != SYS_DMPS_CPUMAC_NETWORK_PORT ))
    {
        return CTC_E_INVALID_CONFIG;
    }

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_STATS_ID, (void *)&mac_id));
    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property_table(lchip, port_type, mac_id, &tbl_id, &index));
    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property_field(lchip, port_type, property, &field_id));

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, &speed_mode));
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_IF_TYPE, &if_type));
    }
    SYS_MAC_STATS_GET_RAM_NUM(lchip, mac_num, speed_mode, if_type);

    do
    {
        cmd = DRV_IOW(tbl_id, field_id);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &value));
        mac_num--;
        if (DRV_FROM_AT(lchip))
        {
            if (CTC_PORT_SPEED_800G == speed_mode || CTC_PORT_IF_CR8 == if_type)
            {/* 800G port use ram0 and ram1 to store stats from Arctic*/
                tbl_id = mac_num > 4 ? McMacStats0Cfg_t : McMacStats1Cfg_t;
            }
            else
            {/* 400G and 200G port use 1 McMacStatsCfg table from Arctic*/
                continue;
            }
        }
        else
        {/*400G port use 4 McMacStatsCfg tables in TsingMa2*/
            tbl_id += (McMacStats1Cfg_t - McMacStats0Cfg_t);
        }
    }while(0 != mac_num);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mac_stats_get_property(uint8 lchip, uint32 gport, sys_mac_stats_property_t property, uint32* p_value)
{
    uint16 lport = 0;
    uint32 tbl_id = 0;
    uint32 field_id = 0;
    uint32 cmd = 0;
    uint32 index = 0;
    uint32 port_type = 0;
    uint32 mac_id = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);
    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    if ((port_type != SYS_DMPS_NETWORK_PORT)&&(port_type != SYS_DMPS_CPUMAC_NETWORK_PORT ))
    {
        return CTC_E_INVALID_CONFIG;
    }

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_STATS_ID, (void *)&mac_id));
    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property_table(lchip, port_type, mac_id, &tbl_id, &index));
    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property_field(lchip, port_type, property, &field_id));

    cmd = DRV_IOR(tbl_id, field_id);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), p_value));

    return CTC_E_NONE;

}

 /*tmm McMacStatsRam0's struct is same as QuadSgmacStatsRam0, so, just use QuadSgmacStatsRam0*/
STATIC int32
_sys_usw_mac_stats_stats_to_basic(uint8 lchip, void* p_stats_ram, ctc_stats_basic_t* p_basic_stats)
{
    uint64 tmp = 0;

    QuadSgmacStatsRam0_s* p_quadmac_stats_ram = NULL;

    p_quadmac_stats_ram = (QuadSgmacStatsRam0_s*)p_stats_ram;

    tmp = p_quadmac_stats_ram->frameCntDataHi_1_0;
    tmp <<= 32;
    tmp |= p_quadmac_stats_ram->frameCntDataLo_31_0;

    p_basic_stats->packet_count = tmp;

    tmp = p_quadmac_stats_ram->byteCntDataHi_7_0;
    tmp <<= 32;
    tmp |= p_quadmac_stats_ram->byteCntDataLo_31_0;

    p_basic_stats->byte_count = tmp;
    return CTC_E_NONE;

}

STATIC INLINE int32
_sys_usw_mac_stats_write_sys_mac_stats(uint8 lchip, uint8 stats_type, void* p_mac_stats, ctc_stats_basic_t* p_stats_basic)
{
    sys_mac_stats_rx_t* p_mac_stats_rx = NULL;
    sys_mac_stats_tx_t* p_mac_stats_tx = NULL;

    if (stats_type < SYS_STATS_MAC_RCV_NUM)
    {
        p_mac_stats_rx = (sys_mac_stats_rx_t*)p_mac_stats;

        p_mac_stats_rx->mac_stats_rx_pkts[stats_type] += p_stats_basic->packet_count;
        p_mac_stats_rx->mac_stats_rx_bytes[stats_type] += p_stats_basic->byte_count;
    }
    else
    {
        p_mac_stats_tx = (sys_mac_stats_tx_t*)p_mac_stats;
        p_mac_stats_tx->mac_stats_tx_pkts[stats_type - SYS_STATS_MAC_SEND_UCAST] += p_stats_basic->packet_count;
        p_mac_stats_tx->mac_stats_tx_bytes[stats_type - SYS_STATS_MAC_SEND_UCAST] += p_stats_basic->byte_count;
    }

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_mac_stats_get_stats_tbl_info(uint8 lchip, uint32 mac_stats_id, uint32* p_tbl_id, uint16* p_tbl_base)
{
    uint32 tbl_step = 0;

    if (DRV_FROM_AT(lchip))
    {
        *p_tbl_id = (mac_stats_id & 0x07) <= 3 ? McMacStatsRam0_t : McMacStatsRam1_t;
        /* one port uses 40 entries that form McMacStatsRam[*p_tbl_base] to McMacStatsRam[*p_tbl_base+39]
         * there are 160 Mac per core in Arctic, so MacID % 160
         */
        *p_tbl_base = ((mac_stats_id%160)/8)*SYS_STATS_MAC_BASED_STATS_XQMAC_RAM_DEPTH + (mac_stats_id & 0x3) * (SYS_STATS_MAC_BASED_STATS_XQMAC_RAM_DEPTH / 4);

        if (mac_stats_id >= SYS_CPU_MAC_ID_MIN && mac_stats_id <= SYS_CPU_MAC_ID_MAX)
        {
            mac_stats_id = mac_stats_id - SYS_CPU_MAC_ID_MIN;
            *p_tbl_id = QuadSgmacStatsRam_t;
            *p_tbl_base = (mac_stats_id & 0x1) * (SYS_STATS_MAC_BASED_STATS_XQMAC_RAM_DEPTH / 4);
        }

    }
    else if(DRV_IS_TMG(lchip))
    {
        *p_tbl_id = QuadSgmacStatsRam_t;
        *p_tbl_base = mac_stats_id * (SYS_STATS_MAC_BASED_STATS_XQMAC_RAM_DEPTH / 4);
    }
    else if(DRV_FROM_TMM(lchip))
    {
        tbl_step = McMacStatsRam1_t - McMacStatsRam0_t;
        *p_tbl_id = McMacStatsRam0_t + ((mac_stats_id%(10*4)) >> 2)* tbl_step;
        *p_tbl_base = (mac_stats_id/(10*4))*SYS_STATS_MAC_BASED_STATS_XQMAC_RAM_DEPTH + (mac_stats_id & 0x3) * (SYS_STATS_MAC_BASED_STATS_XQMAC_RAM_DEPTH / 4);

        if (mac_stats_id >= SYS_CPU_MAC_ID_MIN && mac_stats_id <= SYS_CPU_MAC_ID_MAX)
        {
            mac_stats_id = mac_stats_id - SYS_CPU_MAC_ID_MIN;
            *p_tbl_id = QuadSgmacStatsRam_t;
            *p_tbl_base = (mac_stats_id & 0x3) * (SYS_STATS_MAC_BASED_STATS_XQMAC_RAM_DEPTH / 4);
        }
    }
    else
    {
        tbl_step = QuadSgmacStatsRam1_t - QuadSgmacStatsRam0_t;
        *p_tbl_id = QuadSgmacStatsRam0_t + (mac_stats_id >> 2)* tbl_step;
        *p_tbl_base = (mac_stats_id & 0x3) * (SYS_STATS_MAC_BASED_STATS_XQMAC_RAM_DEPTH / 4);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mac_stats_get_hw_stats(uint8 lchip, uint32 tbl_id, uint16 tbl_base, uint8 stats_type, void* p_mac_stats)
{
    uint32 cmdr = 0;
    ds_t mac_stats;
    ctc_stats_basic_t stats_basic;
    ds_t zero;
    drv_work_platform_type_t platform_type = MAX_WORK_PLATFORM;

    sal_memset(&mac_stats, 0, sizeof(mac_stats));
    sal_memset(&zero, 0, sizeof(zero));
    sal_memset(&stats_basic, 0, sizeof(ctc_stats_basic_t));

    CTC_ERROR_RETURN(drv_get_platform_type(lchip, &platform_type));

    cmdr = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);

    SYS_STATS_DBG_INFO("read mac stats tbl %s[%d] \n", DRV_TABLE_NAME(lchip, tbl_id), stats_type + tbl_base);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, stats_type + tbl_base, DRV_CMD_PP_EN(cmdr), &mac_stats));

    _sys_usw_mac_stats_stats_to_basic(lchip,  &mac_stats, &stats_basic);
    SYS_STATS_DBG_INFO("pkts:%"PRIu64" bytes: %"PRIu64"\n", stats_basic.packet_count, stats_basic.byte_count);

    /* for uml, add this code to support clear after read */
    #if 0 
    uint32 cmdw = 0;
    cmdw = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    if (SW_SIM_PLATFORM == platform_type)
    {
        SYS_STATS_DBG_INFO("clear %s[%d] by software in uml\n", DRV_TABLE_NAME(lchip, tbl_id), stats_type + tbl_base);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, stats_type + tbl_base, DRV_CMD_PP_EN(cmdw), &zero));
    }
    #endif
    
    CTC_ERROR_RETURN(_sys_usw_mac_stats_write_sys_mac_stats(lchip, stats_type, p_mac_stats, &stats_basic));

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_mac_stats_get_sw_stats(uint8 lchip, uint8 mac_type, uint32 mac_id, uint8 stats_type, void* p_mac_stats)
{
    uint32 ram_idx = 0;
    sys_mac_stats_rx_t* p_stats_rx = (sys_mac_stats_rx_t*)p_mac_stats;
    sys_mac_stats_tx_t* p_stats_tx = (sys_mac_stats_tx_t*)p_mac_stats;
    sys_mac_stats_rx_t* p_stats_db_rx = NULL;
    sys_mac_stats_tx_t* p_stats_db_tx = NULL;
    uint8 is_cpumac = 0;

    if(DRV_FROM_TMM(lchip))
    {
        ram_idx = mac_id/4;
        if (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX)
        {
            is_cpumac = 1;
        }
    }
    else
    {
        ram_idx = mac_type;
    }

    if (is_cpumac)
    {
        p_stats_db_rx = &usw_mac_stats_master[lchip]->cpumac_stats[mac_id - SYS_CPU_MAC_ID_MIN].mac_stats_rx[0];
        p_stats_db_tx = &usw_mac_stats_master[lchip]->cpumac_stats[mac_id - SYS_CPU_MAC_ID_MIN].mac_stats_tx[0];
    }
    else
    {
        p_stats_db_rx = &usw_mac_stats_master[lchip]->qmac_stats_table[ram_idx].mac_stats_rx[mac_id % 4];
        p_stats_db_tx = &usw_mac_stats_master[lchip]->qmac_stats_table[ram_idx].mac_stats_tx[mac_id % 4];
    }

    if (stats_type < SYS_STATS_MAC_RCV_NUM)
    {
        p_stats_rx->mac_stats_rx_pkts[RX_TYPE(stats_type)] += p_stats_db_rx->mac_stats_rx_pkts[stats_type];
        p_stats_rx->mac_stats_rx_bytes[RX_TYPE(stats_type)] += p_stats_db_rx->mac_stats_rx_bytes[stats_type];
    }
    else
    {
        p_stats_tx->mac_stats_tx_pkts[TX_TYPE(stats_type)] += p_stats_db_tx->mac_stats_tx_pkts[stats_type - SYS_STATS_MAC_SEND_UCAST];
        p_stats_tx->mac_stats_tx_bytes[TX_TYPE(stats_type)] += p_stats_db_tx->mac_stats_tx_bytes[stats_type - SYS_STATS_MAC_SEND_UCAST];
    }

    return CTC_E_NONE;
}

STATIC INLINE int32
_sys_usw_mac_stats_get_stats_db(uint8 lchip, uint8 mac_type, uint8 stats_type, uint32 mac_id, void** pp_mac_stats)
{
    uint32 ram_idx = 0;
    uint8  is_cpumac = 0;
    if(DRV_FROM_TMM(lchip))
    {
        ram_idx = mac_id>>2;
        if (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX)
        {
            is_cpumac = 1;
        }
    }
    else
    {
        ram_idx = mac_type;
    }

    if (stats_type < SYS_STATS_MAC_RCV_NUM)
    {
        if (is_cpumac)
        {
            *pp_mac_stats = &usw_mac_stats_master[lchip]->cpumac_stats[mac_id - SYS_CPU_MAC_ID_MIN].mac_stats_rx[0];

        }
        else
        {
            *pp_mac_stats = &usw_mac_stats_master[lchip]->qmac_stats_table[ram_idx].mac_stats_rx[mac_id & 3];

        }
    }
    else
    {
        if (is_cpumac)
        {
            *pp_mac_stats = &usw_mac_stats_master[lchip]->cpumac_stats[mac_id - SYS_CPU_MAC_ID_MIN].mac_stats_tx[0];
        }
        else
        {
            *pp_mac_stats = &usw_mac_stats_master[lchip]->qmac_stats_table[ram_idx].mac_stats_tx[mac_id & 3];

        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mac_stats_get_throughput(uint8 lchip, uint32 gport, uint64* p_throughput, sal_systime_t* p_systime)
{
    uint16 drv_lport = 0, sys_lport = 0;

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, drv_lport);
    sys_lport = SYS_MAP_DRV_LPORT_TO_SYS_LPORT(drv_lport);

    p_throughput[CTC_STATS_MAC_STATS_RX] = usw_mac_stats_master[lchip]->mac_throughput.bytes[sys_lport][CTC_STATS_MAC_STATS_RX];
    p_throughput[CTC_STATS_MAC_STATS_TX] = usw_mac_stats_master[lchip]->mac_throughput.bytes[sys_lport][CTC_STATS_MAC_STATS_TX];
    sal_memcpy(p_systime, &(usw_mac_stats_master[lchip]->mac_throughput.timestamp[sys_lport]), sizeof(sal_systime_t));

    SYS_STATS_DBG_INFO("%s %d, tv_sec:%u, tv_usec:%u ms.\n",
                       __FUNCTION__, __LINE__,
                       usw_mac_stats_master[lchip]->mac_throughput.timestamp[sys_lport].tv_sec,
                       usw_mac_stats_master[lchip]->mac_throughput.timestamp[sys_lport].tv_usec);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mac_stats_sync_throughput(uint8 lchip, uint32 gport, uint8* p_addr)
{
    int32  ret = CTC_E_NONE;
#if !defined (EMULATION_ENV) && (0 == SDK_WORK_PLATFORM)
    void*  p_mac_stats = NULL;
    uint32 tbl_id_base = DRV_FROM_TMM(lchip) ? McMacStatsRam0_t : QuadSgmacStatsRam0_t;
    uint8 mac_type = 0;
#endif
    uint8  stats_type = 0;
    uint16 stats_offset = 0;
    uint16  tbl_base = 0;
    uint32 cmdr = 0;
    uint32 mac_ipg = 0;
    uint32 tbl_id = 0;
    ctc_mac_stats_dir_t dir = CTC_STATS_MAC_STATS_RX;
    ds_t mac_stats;
    ctc_stats_basic_t stats_basic;
    uint8  index = 0;
    uint8 is_network = 0;
    uint16 lport = 0;
    uint8 mac_num = 0;
    uint32 mac_id = 0;
    uint32 port_type = 0;
    uint32 speed_mode = 0;
    uint32 mac_stats_id = 0;
    uint32 if_type = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STATS_INIT_CHECK();

    if (CTC_IS_CPU_PORT(gport) && DRV_FROM_TMM(lchip))
    {
        index = gport & 0xf;
        if(MCHIP_DMPS(lchip)->cpumac_get_lport_info_by_inner_idx)
        {
            ret = MCHIP_DMPS(lchip)->cpumac_get_lport_info_by_inner_idx(lchip,index,&lport,&is_network);
        }
    }
    else
    {
        lport = CTC_MAP_GPORT_TO_LPORT(gport);
    }
    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    if (SYS_DMPS_NETWORK_PORT != port_type && SYS_DMPS_CPU_MAC_PORT != port_type && SYS_DMPS_CPUMAC_NETWORK_PORT != port_type)
    {
        return CTC_E_INVALID_CONFIG;
    }
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_STATS_ID, (void *)&mac_stats_id));
    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_tbl_info(lchip, mac_stats_id, &tbl_id, &tbl_base));
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, (void *)&speed_mode));
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_IF_TYPE, &if_type));
    }
    SYS_MAC_STATS_GET_RAM_NUM(lchip, mac_num, speed_mode, if_type);
#if !defined (EMULATION_ENV) && (0 == SDK_WORK_PLATFORM)
    mac_type = tbl_id-tbl_id_base;
#endif
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &mac_id));
    ret = sys_usw_port_api_get_property(lchip, gport, CTC_PORT_PROP_MAC_TX_IPG, &mac_ipg);
    if (ret < 0)
    {
        mac_ipg = 12;
    }
    else
    {
        mac_ipg &= 0xFF;
    }
    
    if (MCHIP_MAC_STATS(lchip)->stats_sync_throughput)
    {
        usw_mac_stats_master[lchip]->mac_throughput.bytes[lport][CTC_STATS_MAC_STATS_RX] = 0;
        usw_mac_stats_master[lchip]->mac_throughput.bytes[lport][CTC_STATS_MAC_STATS_TX] = 0;
        do
        {
            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_tbl_info(lchip, mac_stats_id, &tbl_id, &tbl_base));
            CTC_ERROR_RETURN(MCHIP_MAC_STATS(lchip)->stats_sync_throughput(lchip, lport, tbl_id, tbl_base, mac_ipg));
            mac_num--;
            mac_stats_id ++;
        }
        while (0 != mac_num);
        sal_gettime(&(usw_mac_stats_master[lchip]->mac_throughput.timestamp[lport]));
        return CTC_E_NONE;
    }

    do
    {
        cmdr = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        for (stats_type = SYS_STATS_MAC_RCV_GOOD_UCAST; stats_type < SYS_STATS_MAC_STATS_TYPE_NUM; stats_type++)
        {
            if (!((SYS_STATS_MAC_RCV_GOOD_UCAST == stats_type) || (SYS_STATS_MAC_RCV_GOOD_MCAST == stats_type)
                || (SYS_STATS_MAC_RCV_GOOD_BCAST == stats_type) || (SYS_STATS_MAC_SEND_UCAST == stats_type)
                || (SYS_STATS_MAC_SEND_MCAST == stats_type) || (SYS_STATS_MAC_SEND_BCAST == stats_type)))
            {
                continue;
            }

            sal_memset(&mac_stats, 0, sizeof(mac_stats));
            sal_memset(&stats_basic, 0, sizeof(ctc_stats_basic_t));

            if (NULL != p_addr)
            {
                stats_offset = stats_type * DRV_ADDR_BYTES_PER_ENTRY;
                sal_memcpy(&mac_stats, (uint8*)p_addr + stats_offset, DRV_FROM_TMM(lchip) ? sizeof(McMacStatsRam0_m) : sizeof(QuadSgmacStatsRam0_m));
                _sys_usw_mac_stats_stats_to_basic(lchip, &mac_stats, &stats_basic);
            }
            else
            {
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, stats_type + tbl_base, cmdr, &mac_stats));
                _sys_usw_mac_stats_stats_to_basic(lchip, &mac_stats, &stats_basic);
#if !defined (EMULATION_ENV) && (0 == SDK_WORK_PLATFORM)
                _sys_usw_mac_stats_get_stats_db(lchip, mac_type, stats_type, mac_id, (void**)(&p_mac_stats));
                CTC_ERROR_RETURN(_sys_usw_mac_stats_write_sys_mac_stats(lchip, stats_type, p_mac_stats, &stats_basic));
#endif
            }
            dir = (stats_type < SYS_STATS_MAC_SEND_UCAST) ? CTC_STATS_MAC_STATS_RX : CTC_STATS_MAC_STATS_TX;
            usw_mac_stats_master[lchip]->mac_throughput.bytes[lport][dir] += (stats_basic.byte_count + stats_basic.packet_count*(8 + mac_ipg));
        }
        mac_num--;
        mac_id += SYS_USW_400G_MAC_ID_OFFSET;
        mac_stats_id += SYS_USW_400G_MAC_ID_OFFSET;
    }
    while (0 != mac_num);
    sal_gettime(&(usw_mac_stats_master[lchip]->mac_throughput.timestamp[lport]));

    return CTC_E_NONE;
}

STATIC int32
_sys_at_mac_stats_sync_cb_func(uint8 lchip, uint32* mac_id, uint32* tbl_id)
{
    uint16 tbl_base = 0;
    /*1. get table id in order to get db */
    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_tbl_info(lchip, *mac_id, tbl_id, &tbl_base));
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mac_stats_sync_cb_func(uint8 lchip, uint32* mac_id, uint32* tbl_id)
{
    uint16 lport = 0;
    uint32 gport = 0;
    uint16  tbl_base = 0;
    uint8  gchip_id = 0;
    uint32 speed_mode = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    if (DRV_IS_TSINGMA(lchip))
    {
        lport = sys_usw_dmps_get_lport_with_mac_tbl_id(lchip, (*mac_id));
    }
    else
    {
        lport = sys_usw_port_api_get_lport_with_mac(lchip, (*mac_id));
    }

    if (SYS_COMMON_USELESS_MAC == lport)
    {
        lport = sys_usw_port_api_get_lport_with_mac(lchip, ((*mac_id)/40)*40);
        if(SYS_COMMON_USELESS_MAC == lport)
        {
            return CTC_E_NONE;
        }
        if ((*mac_id) >= SYS_CPU_MAC_ID_MIN && (*mac_id) <= SYS_CPU_MAC_ID_MAX)
        {
            gport = 0x20000000 + ((*mac_id) - SYS_CPU_MAC_ID_MIN);
        }
        else
        {
            gport = CTC_MAP_LPORT_TO_GPORT(gchip_id, lport);
        }
        dmps_port_info.gport = gport;
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, &speed_mode));
        if ((CTC_PORT_SPEED_400G == speed_mode) && (0 == (*mac_id)%4))
        {
            /*1. get table id in order to get db */
            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_tbl_info(lchip, (*mac_id), tbl_id, &tbl_base));
        }
        else
        {
            return CTC_E_NONE;
        }
    }
    else
    {
        uint8 flexe_aps = 0;
        uint32 flexe_mac_id = 0;
        if ((*mac_id) >= SYS_CPU_MAC_ID_MIN && (*mac_id) <= SYS_CPU_MAC_ID_MAX)
        {
            gport = 0x20000000 + ((*mac_id) - SYS_CPU_MAC_ID_MIN);
        }
        else
        {
            gport = CTC_MAP_LPORT_TO_GPORT(gchip_id, lport);
        }
        dmps_port_info.gport = gport;
        /*1. get table id in order to get db */
        CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_tbl_info(lchip, (*mac_id), tbl_id, &tbl_base));
        sys_usw_dmps_get_flexe_aps(lchip, lport, &flexe_aps, &flexe_mac_id);
        if (!flexe_aps )
        {
            CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, (void*)mac_id));
        }
    }

    return CTC_E_NONE;
}


STATIC int32
sys_usw_mac_stats_sync_dma_stats(uint8 lchip, void* p_data)
{
    void*  p_mac_stats = NULL;
    uint8  stats_type = 0;
    uint16 stats_offset = 0;
    uint32 tbl_id = 0xFFFFFFFF;
    uint32 tbl_id_base = DRV_IS_TMG(lchip)?QuadSgmacStatsRam_t:(DRV_FROM_TMM(lchip) ? McMacStatsRam0_t : QuadSgmacStatsRam0_t);
    uint32  mac_id = 0;
    uint8* p_addr = NULL;
    QuadSgmacStatsRam0_s stats_ram;
    ctc_stats_basic_t stats_basic;
    sys_dma_reg_t* p_dma_reg = (sys_dma_reg_t*)p_data;
    SYS_STATS_INIT_CHECK();

    mac_id = *((uint16*)p_dma_reg->p_ext);
    p_addr = p_dma_reg->p_data;

    STATS_LOCK();

    CTC_ERROR_RETURN_UNLOCK(usw_mac_stats_master[lchip]->sync_cb(lchip, &mac_id, &tbl_id));
    if(0xFFFFFFFF == tbl_id)
    {
        STATS_UNLOCK();
        return CTC_E_NONE;
    }
    /*2. get detail info from dma data & store in db*/
    for (stats_type = 0; stats_type < SYS_STATS_MAC_STATS_TYPE_NUM; stats_type++)
    {
        _sys_usw_mac_stats_get_stats_db(lchip, tbl_id-tbl_id_base, stats_type, mac_id, (void**)(&p_mac_stats));
        stats_offset = stats_type * DRV_ADDR_BYTES_PER_ENTRY;

        sal_memcpy(&stats_ram, (uint8*)p_addr + stats_offset, sizeof(stats_ram));
        sal_memset(&stats_basic, 0, sizeof(ctc_stats_basic_t));

        _sys_usw_mac_stats_stats_to_basic(lchip, &stats_ram, &stats_basic);
        _sys_usw_mac_stats_write_sys_mac_stats(lchip, stats_type, p_mac_stats, &stats_basic);
    }

    STATS_UNLOCK();

    return CTC_E_NONE;
}
#define ___________MAC_STATS_API________________________
int32
sys_usw_mac_stats_set_global_property_hold(uint8 lchip, bool enable)
{
    uint32 tmp = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    tmp = (FALSE == enable) ? 0 : 1;

    CTC_ERROR_RETURN(_sys_usw_mac_stats_set_global_property(lchip, SYS_MAC_STATS_PROPERTY_HOLD, tmp));

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_get_global_property_hold(uint8 lchip, bool* p_enable)
{
    uint32 tmp = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_enable);

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_global_property(lchip, SYS_MAC_STATS_PROPERTY_HOLD, &tmp));

    *p_enable = (tmp>0 ? TRUE: FALSE);

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_set_global_property_saturate(uint8 lchip, bool enable)
{
    uint32 tmp = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    tmp = (FALSE == enable) ? 0 : 1;

    CTC_ERROR_RETURN(_sys_usw_mac_stats_set_global_property(lchip, SYS_MAC_STATS_PROPERTY_SATURATE, tmp));

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_get_global_property_saturate(uint8 lchip, bool* p_enable)
{
    uint32 tmp = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_enable);

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_global_property(lchip, SYS_MAC_STATS_PROPERTY_SATURATE, &tmp));

    *p_enable = (tmp>0 ? TRUE: FALSE);

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_set_global_property_clear_after_read(uint8 lchip, bool enable)
{
    uint32 tmp = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    tmp = (FALSE == enable) ? 0 : 1;

    CTC_ERROR_RETURN(_sys_usw_mac_stats_set_global_property(lchip, SYS_MAC_STATS_PROPERTY_CLEAR, tmp));

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_get_global_property_clear_after_read(uint8 lchip, bool* p_enable)
{
    uint32 tmp = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_enable);

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_global_property(lchip, SYS_MAC_STATS_PROPERTY_CLEAR, &tmp));

    *p_enable = (tmp>0 ? TRUE: FALSE);

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_set_property_mtu1(uint8 lchip, uint32 gport, uint16 length)
{
    uint32 mtu2_len = 0;
    uint32 tmp = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    tmp = length;

    CTC_VALUE_RANGE_CHECK(tmp, SYS_STATS_MTU1_PKT_MIN_LENGHT, SYS_STATS_MTU_PKT_MAX_LENGTH);

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property(lchip, gport, SYS_MAC_STATS_PROPERTY_MTU2, &mtu2_len));
    if ((tmp > mtu2_len) && (SYS_STATS_MTU1_PKT_MIN_LENGHT <= mtu2_len))
    {
        return CTC_E_INVALID_PARAM;
    }
    CTC_ERROR_RETURN(_sys_usw_mac_stats_set_property(lchip, gport, SYS_MAC_STATS_PROPERTY_MTU1, length));

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_get_property_mtu1(uint8 lchip, uint32 gport, uint16* p_length)
{
    uint32 value = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_length);

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property(lchip, gport, SYS_MAC_STATS_PROPERTY_MTU1, &value));
    *p_length = (uint16)value;

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_set_property_mtu2(uint8 lchip, uint32 gport, uint16 length)
{
    uint32 mtu1_len = 0;
    uint32 tmp = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    tmp = length;

    CTC_MIN_VALUE_CHECK(tmp, SYS_STATS_MTU2_PKT_MIN_LENGTH);
    CTC_MAX_VALUE_CHECK(tmp, SYS_STATS_MTU_PKT_MAX_LENGTH);

    /*mtu2 length must greater than or equal to mtu1 length, when mtu2 greater than or equal to 2048*/
    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property(lchip, gport, SYS_MAC_STATS_PROPERTY_MTU1, &mtu1_len));
    if (tmp < mtu1_len && (SYS_STATS_MTU1_PKT_MIN_LENGHT <= tmp))
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_ERROR_RETURN(_sys_usw_mac_stats_set_property(lchip, gport, SYS_MAC_STATS_PROPERTY_MTU2, length));

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_get_property_mtu2(uint8 lchip, uint32 gport, uint16* p_length)
{
    uint32 value = 0;

    SYS_STATS_DBG_FUNC();

    SYS_STATS_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_length);

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property(lchip, gport, SYS_MAC_STATS_PROPERTY_MTU2, &value));
    *p_length = (uint16)value;

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_set_property_pfc(uint8 lchip, uint32 gport, uint8 enable)
{
    uint32 tmp = 0;

    SYS_STATS_INIT_CHECK();
    tmp = enable;

    CTC_MAX_VALUE_CHECK(tmp, 1);
    SYS_MAP_GPORT_TO_LCHIP1(gport, lchip);
    CTC_ERROR_RETURN(_sys_usw_mac_stats_set_property(lchip, gport, SYS_MAC_STATS_PROPERTY_PFC, tmp));

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_get_property_pfc(uint8 lchip, uint32 gport, uint8* p_enable)
{
    uint32 value = 0;

    SYS_STATS_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_enable);
    SYS_MAP_GPORT_TO_LCHIP1(gport, lchip);
    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_property(lchip, gport, SYS_MAC_STATS_PROPERTY_PFC, &value));
    *p_enable = (value > 0 ? 1: 0);

    return CTC_E_NONE;
}

int32
_sys_usw_mac_stats_get_pfc_stats(uint8 lchip, uint16 mac_stats_id, uint16 mac_id, uint8 dir, ctc_mac_stats_t* p_stats)
{
    uint32 tbl_step = Sgmac1PfcPktRxStats_t - Sgmac0PfcPktRxStats_t;
    uint32 tbl_id = 0;
    uint32 index = 0;
    uint32 cmd = 0;
    uint8 i = 0;
    uint64* stats = 0;
    uint64 stats1=0;

    Sgmac0PfcPktRxStats_m pfc_stats;

    tbl_id = Sgmac0PfcPktRxStats_t+tbl_step*(mac_id%MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM))+MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM)*dir;
    index = mac_id/MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM);
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &pfc_stats);

    stats = (dir? &usw_mac_stats_master[lchip]->qmgc_pfc_stats_table[mac_id].mac_stats_tx[0]:&usw_mac_stats_master[lchip]->qmgc_pfc_stats_table[mac_id].mac_stats_rx[0]);

    for(i=0;i<8;i++)
    {
        GetSgmac0PfcPktRxStats(A,sgmac0PfcPktPri0RxCnt_f+i,&pfc_stats,&stats1);
        *stats=*stats+stats1;
        if(p_stats == NULL)
        {
            stats++;
            continue;
        }
        if(dir)
        {
            p_stats->u.stats_detail.stats.tx_stats.pfc_pkts[i] = *stats;
        }
        else
        {
            p_stats->u.stats_detail.stats.rx_stats.pfc_pkts[i] = *stats;
        }
        stats++;
    }
    return CTC_E_NONE;
}
int32
_sys_usw_mac_stats_get_rx_stats(uint8 lchip, uint16 mac_stats_id, uint16 mac_id, ctc_mac_stats_t* p_stats)
{
    uint8  stats_type = 0;
    uint16  tbl_base = 0;
    uint32 tbl_id = 0;
    uint32 tbl_id_base = DRV_FROM_TMM(lchip) ? McMacStatsRam0_t : QuadSgmacStatsRam0_t;
    sys_mac_stats_rx_t* p_mac_stats = NULL;
    sys_mac_stats_rx_t tmp_mac_stats;
    uint8 mac_type = 0;

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_tbl_info(lchip, mac_stats_id, &tbl_id, &tbl_base));

    SYS_STATS_DBG_INFO("tbl_id:%d mac_id:%d, base:%d\n", tbl_id, mac_id, tbl_base);

    sal_memset(&tmp_mac_stats, 0, sizeof(tmp_mac_stats));
    mac_type = tbl_id-tbl_id_base;
    if (MCHIP_MAC_STATS(lchip)->stats_get_mac_stats)
    {
        CTC_ERROR_RETURN(MCHIP_MAC_STATS(lchip)->stats_get_mac_stats(lchip, tbl_id, tbl_base, CTC_STATS_MAC_STATS_RX, &tmp_mac_stats));/*lchip is base*/
    }
    else
    {
        for (stats_type = SYS_STATS_MAC_RCV_GOOD_UCAST; stats_type < SYS_STATS_MAC_RCV_NUM; stats_type++)
        {
            if (SYS_MAC_STATS_STORE_SW == usw_mac_stats_master[lchip]->store_mode)
            {
                switch (usw_mac_stats_master[lchip]->query_mode)
                {
                    case CTC_STATS_QUERY_MODE_IO:
                        {
                            /*
                             * SDK maintain mac stats db and use dma callback,
                             * user app do not need db to stroe every io result.
                            */

                            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_db(lchip, mac_type, stats_type, mac_id, (void**)(&p_mac_stats)));
                            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_hw_stats(lchip, tbl_id, tbl_base, stats_type, p_mac_stats));
                            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_sw_stats(lchip, mac_type, mac_id, stats_type, &tmp_mac_stats));
                            break;
                        }
                    case CTC_STATS_QUERY_MODE_POLL:
                        {
                            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_sw_stats(lchip, mac_type, mac_id, stats_type, &tmp_mac_stats));
                            break;
                        }
                    default :
                        break;
                }
            }
            else
            {
                /*
                 *  SDK do not maintain mac stats db and no dma callback,
                 *  the internal time of user app read stats should less than counter overflow.
                */

                CTC_ERROR_RETURN(_sys_usw_mac_stats_get_hw_stats(lchip, tbl_id, tbl_base, stats_type, &tmp_mac_stats));
            }
        }
    }
    if (CTC_STATS_MODE_PLUS == p_stats->stats_mode)
    {
        ctc_stats_mac_rec_plus_t* p_rx_stats_plus = &(p_stats->u.stats_plus.stats.rx_stats_plus);

        p_rx_stats_plus->ucast_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_UCAST)];
        p_rx_stats_plus->all_octets += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_63B)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_BAD_63B)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_64B)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_127B)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_255B)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_511B)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_1023B)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_1518B)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_2047B)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_MTU1)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_MTU1_TO_MTU2)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_BAD_MTU1_TO_MTU2)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_JUMBO)] + \
                                      tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_BAD_JUMBO)];
        p_rx_stats_plus->all_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_64B)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_63B)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_BAD_63B)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_127B)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_255B)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_511B)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_1023B)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_1518B)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_2047B)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_MTU1)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_MTU1_TO_MTU2)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_BAD_MTU1_TO_MTU2)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_JUMBO)] + \
                                    tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_BAD_JUMBO)];
        p_rx_stats_plus->bcast_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_BCAST)];
        p_rx_stats_plus->crc_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_FCS_ERROR)];
        p_rx_stats_plus->drop_events += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_MAC_OVERRUN)];
        p_rx_stats_plus->error_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_FCS_ERROR)] + \
                                      tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_MAC_OVERRUN)];
        p_rx_stats_plus->fragments_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_63B)] + tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_BAD_63B)];
        p_rx_stats_plus->giants_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_JUMBO)];
        p_rx_stats_plus->jumbo_events += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_JUMBO)] + tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_BAD_JUMBO)];
        p_rx_stats_plus->mcast_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_MCAST)];
        p_rx_stats_plus->overrun_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_MAC_OVERRUN)];
        p_rx_stats_plus->pause_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_NORMAL_PAUSE)] + tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_PFC_PAUSE)];
        p_rx_stats_plus->runts_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_63B)];
    }
    else
    {
        ctc_stats_mac_rec_t* p_stats_mac_rec = &p_stats->u.stats_detail.stats.rx_stats;

        p_stats_mac_rec->good_ucast_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_UCAST)];
        p_stats_mac_rec->good_ucast_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_UCAST)];
        p_stats_mac_rec->good_mcast_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_MCAST)];
        p_stats_mac_rec->good_mcast_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_MCAST)];
        p_stats_mac_rec->good_bcast_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_BCAST)];
        p_stats_mac_rec->good_bcast_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_BCAST)];
        p_stats_mac_rec->good_normal_pause_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_NORMAL_PAUSE)];
        p_stats_mac_rec->good_normal_pause_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_NORMAL_PAUSE)];
        p_stats_mac_rec->good_pfc_pause_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_PFC_PAUSE)];
        p_stats_mac_rec->good_pfc_pause_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_PFC_PAUSE)];
        p_stats_mac_rec->good_control_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_CONTROL)];
        p_stats_mac_rec->good_control_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_CONTROL)];
        p_stats_mac_rec->fcs_error_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_FCS_ERROR)];
        p_stats_mac_rec->fcs_error_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_FCS_ERROR)];
        p_stats_mac_rec->mac_overrun_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_MAC_OVERRUN)];
        p_stats_mac_rec->mac_overrun_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_MAC_OVERRUN)];

        p_stats_mac_rec->good_63_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_63B)];
        p_stats_mac_rec->good_63_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_63B)];
        p_stats_mac_rec->bad_63_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_BAD_63B)];
        p_stats_mac_rec->bad_63_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_BAD_63B)];
        p_stats_mac_rec->good_jumbo_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_JUMBO)];
        p_stats_mac_rec->good_jumbo_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_JUMBO)];
        p_stats_mac_rec->bad_jumbo_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_BAD_JUMBO)];
        p_stats_mac_rec->bad_jumbo_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_BAD_JUMBO)];
        p_stats_mac_rec->pkts_64 += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_64B)];
        p_stats_mac_rec->bytes_64 += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_64B)];
        p_stats_mac_rec->pkts_65_to_127 += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_127B)];
        p_stats_mac_rec->bytes_65_to_127 += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_127B)];
        p_stats_mac_rec->pkts_128_to_255 += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_255B)];
        p_stats_mac_rec->bytes_128_to_255 += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_255B)];
        p_stats_mac_rec->pkts_256_to_511 += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_511B)];
        p_stats_mac_rec->bytes_256_to_511 += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_511B)];
        p_stats_mac_rec->pkts_512_to_1023 += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_1023B)];
        p_stats_mac_rec->bytes_512_to_1023 += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_1023B)];
        p_stats_mac_rec->pkts_1024_to_1518 += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_1518B)];
        p_stats_mac_rec->bytes_1024_to_1518 += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_1518B)];
        p_stats_mac_rec->pkts_1519_to_2047 += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_2047B)];
        p_stats_mac_rec->bytes_1519_to_2047 += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_2047B)];
        p_stats_mac_rec->pkts_2048_to_mtu1 += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_MTU1)];
        p_stats_mac_rec->bytes_2048_to_mtu1 += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_MTU1)];
        p_stats_mac_rec->pkts_mtu1_to_mtu2 += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_MTU1_TO_MTU2)];
        p_stats_mac_rec->bytes_mtu1_to_mtu2 += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_MTU1_TO_MTU2)];
        p_stats_mac_rec->good_oversize_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_JUMBO)] + \
                                               tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_BAD_JUMBO)] + \
                                               tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_MTU1_TO_MTU2)];
        p_stats_mac_rec->good_oversize_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_JUMBO)] + \
                                                tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_BAD_JUMBO)] + \
                                                tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_MTU1_TO_MTU2)];
        p_stats_mac_rec->good_undersize_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_63B)];
        p_stats_mac_rec->good_undersize_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_63B)];
        p_stats_mac_rec->good_pause_pkts += tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_NORMAL_PAUSE)] + \
                                             tmp_mac_stats.mac_stats_rx_pkts[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_PFC_PAUSE)];
        p_stats_mac_rec->good_pause_bytes += tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_NORMAL_PAUSE)] + \
                                             tmp_mac_stats.mac_stats_rx_bytes[RX_TYPE(SYS_STATS_MAC_RCV_GOOD_PFC_PAUSE)];
        if(DRV_IS_TMG(lchip))
        {
            _sys_usw_mac_stats_get_pfc_stats(lchip, mac_stats_id, mac_id, 0, p_stats);
        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_get_rx_stats(uint8 lchip, uint32 gport, ctc_mac_stats_t* p_stats)
{
    uint8 mac_num = 0;
    uint16 lport = 0;
    ctc_mac_stats_t* p_tmp_stats = NULL;
    uint8 client_bind = 1;
    uint32 mac_stats_id = 0;
    uint32 mac_id = 0;
    uint32 flexe_mac_id = 0;
    uint32 port_type = 0;
    uint8 flexe_aps = 0;
    uint32 speed_mode = 0;
    uint32 if_type = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STATS_DBG_FUNC();
    SYS_STATS_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_stats);
    if (SYS_CB(SYS_CB_TSX_GET_MAC_STATS_EN,lchip))
    {
        SYS_STATS_DBG_ERROR("tsx already controled mac stats\n");
        return CTC_E_IN_USE;
    }
    if (!DRV_FROM_AT(lchip))
    {
        MCHIP_DMA(lchip)->dma_stats_func(lchip, SYS_DMA_PORT_STATS_CHAN_ID);
    }
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);
    STATS_LOCK();

    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    if (SYS_DMPS_NETWORK_PORT != port_type && SYS_DMPS_CPU_MAC_PORT != port_type && SYS_DMPS_CPUMAC_NETWORK_PORT != port_type)
    {
        STATS_UNLOCK();
        return CTC_E_INVALID_CONFIG;
    }
    CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, &speed_mode));
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_IF_TYPE, &if_type));
    }
    if (p_stats->p_next)
    {
        sys_usw_dmps_get_flexe_aps(lchip, lport, &flexe_aps, &flexe_mac_id);
        client_bind = flexe_aps?2:1;
    }
    do
    {
        client_bind--;
    	SYS_MAC_STATS_GET_RAM_NUM(lchip, mac_num, speed_mode, if_type);
        if (1 == client_bind)
        {
            mac_id = flexe_mac_id;
            mac_stats_id = flexe_mac_id;
            p_tmp_stats = p_stats->p_next;
        }
        else
        {
            CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &mac_id));
            CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_STATS_ID, (void *)&mac_stats_id));
            p_tmp_stats = p_stats;
        }
        sal_memset(&p_tmp_stats->u, 0, sizeof(p_tmp_stats->u));
        do
        {
            CTC_ERROR_RETURN_UNLOCK(_sys_usw_mac_stats_get_rx_stats(lchip, mac_stats_id, mac_id, p_tmp_stats));
            mac_num--;
            if (DRV_FROM_AT(lchip))
            {
                mac_stats_id++;
                mac_id++;
            }
            else
            {
                mac_stats_id += SYS_USW_400G_MAC_ID_OFFSET;
                mac_id += SYS_USW_400G_MAC_ID_OFFSET;
            }

        }while(0 < mac_num);
    }while(0 < client_bind);
    STATS_UNLOCK();

    return CTC_E_NONE;

}

int32
_sys_usw_mac_stats_clear_rx_stats(uint8 lchip, uint16 mac_stats_id, uint16 mac_id)
{
    uint16  base = 0;
    uint16 index = 0;
    uint32 cmd = 0;
    uint32 tbl_id = 0;
    uint32 tbl_id_base = DRV_FROM_TMM(lchip) ? McMacStatsRam0_t : QuadSgmacStatsRam0_t;
    ds_t qmac_stats_ram;
    uint32 ram_idx = 0;
    uint8  is_cpumac = 0;
    sal_memset(&qmac_stats_ram, 0, sizeof(ds_t));

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_tbl_info(lchip, mac_stats_id, &tbl_id, &base));
    if (MCHIP_MAC_STATS(lchip)->stats_clear_mac_stats)
    {
        CTC_ERROR_RETURN(MCHIP_MAC_STATS(lchip)->stats_clear_mac_stats(lchip, tbl_id, base, CTC_STATS_MAC_STATS_RX));/*lchip is base*/
        return CTC_E_NONE;
    }
    ram_idx = tbl_id - tbl_id_base;
    if (CTC_STATS_QUERY_MODE_IO == usw_mac_stats_master[lchip]->query_mode)
    {
#if (0 == SDK_WORK_PLATFORM)
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
#else
        /* for uml, add this code to support clear after read */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
#endif
        for (index = SYS_STATS_MAC_RCV_GOOD_UCAST + base; index < SYS_STATS_MAC_RCV_NUM + base; index++)
        {
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &qmac_stats_ram));
        }
    }
    if (DRV_FROM_AT(lchip))
    {
        return CTC_E_NONE;
    }
    if (DRV_FROM_TMM(lchip))
    {
        ram_idx = mac_id / 4;
        if (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX)
        {
            is_cpumac = 1;
        }
    }

    if (is_cpumac)
    {
        sal_memset(&usw_mac_stats_master[lchip]->cpumac_stats[mac_id - SYS_CPU_MAC_ID_MIN].mac_stats_rx[0], 0, sizeof(sys_mac_stats_rx_t));
    }
    else
    {
        sal_memset(&usw_mac_stats_master[lchip]->qmac_stats_table[ram_idx].mac_stats_rx[mac_id % 4], 0, sizeof(sys_mac_stats_rx_t));
    }

    if(DRV_IS_TMG(lchip))
    {
        _sys_usw_mac_stats_get_pfc_stats(lchip, mac_stats_id, mac_id, 0, NULL);
        sal_memset(&usw_mac_stats_master[lchip]->qmgc_pfc_stats_table[mac_id].mac_stats_rx, 0, sizeof(uint64)*8);
    }

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_clear_rx_stats(uint8 lchip, uint32 gport)
{
    uint32 mac_id = 0;
    uint8 mac_num = 0;
    uint16 lport = 0;
    uint8 client_bind = 1;
    uint32 mac_stats_id = 0;
    uint32 flexe_mac_id = 0;
    uint32 port_type = 0;
    uint8 flexe_aps = 0;
    uint32 speed_mode = 0;
    uint32 if_type = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STATS_DBG_FUNC();
    SYS_STATS_INIT_CHECK();
    if (!DRV_FROM_AT(lchip))
    {
        MCHIP_DMA(lchip)->dma_stats_func(lchip, SYS_DMA_PORT_STATS_CHAN_ID);
    }
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);
    dmps_port_info.gport = gport;
    STATS_LOCK();
    CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    if (SYS_DMPS_NETWORK_PORT != port_type && SYS_DMPS_CPU_MAC_PORT != port_type && SYS_DMPS_CPUMAC_NETWORK_PORT != port_type)
    {
        STATS_UNLOCK();
        return CTC_E_INVALID_CONFIG;
    }
    CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, &speed_mode));
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_IF_TYPE, &if_type));
    }
    sys_usw_dmps_get_flexe_aps(lchip, lport, &flexe_aps, &flexe_mac_id);
    client_bind = flexe_aps?2:1;

    do
    {
        client_bind--;
    	SYS_MAC_STATS_GET_RAM_NUM(lchip, mac_num, speed_mode, if_type);
        if (1 == client_bind)
        {
            mac_stats_id = flexe_mac_id;
            mac_id = flexe_mac_id;
        }
        else
        {
            CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_STATS_ID, (void *)&mac_stats_id));
            CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &mac_id));
        }
        do
        {
            CTC_ERROR_RETURN_UNLOCK(_sys_usw_mac_stats_clear_rx_stats(lchip, mac_stats_id, mac_id));
			if (DRV_FROM_AT(lchip))
			{
				mac_stats_id++;
				mac_id++;
			}
			else
			{
	            mac_stats_id += SYS_USW_400G_MAC_ID_OFFSET;
	            mac_id += SYS_USW_400G_MAC_ID_OFFSET;
            }
            mac_num--;
        }while(0 < mac_num);
    }while(0 < client_bind);
    STATS_UNLOCK();

    return CTC_E_NONE;
}

int32
_sys_usw_mac_stats_get_tx_stats(uint8 lchip, uint16 mac_stats_id, uint16 mac_id, ctc_mac_stats_t* p_stats)
{
    uint8  stats_type = 0;
    uint16  tbl_base = 0;
    uint32 tbl_id = 0;
    uint32 tbl_id_base = DRV_FROM_TMM(lchip) ? McMacStatsRam0_t : QuadSgmacStatsRam0_t;
    sys_mac_stats_tx_t* p_mac_stats = NULL;
    sys_mac_stats_tx_t tmp_mac_stats;
    uint8 mac_type = 0;

    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_tbl_info(lchip, mac_stats_id, &tbl_id, &tbl_base));

    SYS_STATS_DBG_INFO("tbl_id:%d mac_id:%d, base:%d\n", tbl_id, mac_id, tbl_base);

    sal_memset(&tmp_mac_stats, 0, sizeof(tmp_mac_stats));
    mac_type = tbl_id-tbl_id_base;
    if (MCHIP_MAC_STATS(lchip)->stats_get_mac_stats)
    {
        CTC_ERROR_RETURN(MCHIP_MAC_STATS(lchip)->stats_get_mac_stats(lchip, tbl_id, tbl_base, CTC_STATS_MAC_STATS_TX, &tmp_mac_stats));/*lchip is base*/
    }
    else
    {
        for (stats_type = SYS_STATS_MAC_SEND_UCAST; stats_type < SYS_STATS_MAC_STATS_TYPE_NUM; stats_type++)
        {
            if (SYS_MAC_STATS_STORE_SW == usw_mac_stats_master[lchip]->store_mode)
            {
                switch (usw_mac_stats_master[lchip]->query_mode)
                {
                    case CTC_STATS_QUERY_MODE_IO:
                        {
                            /*
                             * SDK maintain mac stats db and use dma callback,
                             * user app do not need db to stroe every io result.
                            */

                            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_db(lchip, mac_type, stats_type, mac_id, (void**)(&p_mac_stats)));
                            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_hw_stats(lchip, tbl_id, tbl_base, stats_type, p_mac_stats));
                            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_sw_stats(lchip, mac_type, mac_id, stats_type, &tmp_mac_stats));
                            break;
                        }
                    case CTC_STATS_QUERY_MODE_POLL:
                        {
                            CTC_ERROR_RETURN(_sys_usw_mac_stats_get_sw_stats(lchip, mac_type, mac_id, stats_type, &tmp_mac_stats));
                            break;
                        }
                    default :
                        break;
                }
            }
            else
            {
                /*
                 *  SDK do not maintain mac stats db and no dma callback,
                 *  the internal time of user app read stats should less than counter overflow.
                */

                CTC_ERROR_RETURN(_sys_usw_mac_stats_get_hw_stats(lchip, tbl_id, tbl_base, stats_type, &tmp_mac_stats));
            }
        }
    }
    if (CTC_STATS_MODE_PLUS == p_stats->stats_mode)
    {
        ctc_stats_mac_snd_plus_t* p_tx_stats_plus = &(p_stats->u.stats_plus.stats.tx_stats_plus);
        p_tx_stats_plus->all_octets += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_63B)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_64B)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_127B)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_255B)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_511B)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_1023B)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_1518B)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_2047B)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_MTU1)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_MTU2)] + \
                                      tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_JUMBO)];
        p_tx_stats_plus->all_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_63B)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_64B)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_127B)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_255B)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_511B)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_1023B)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_1518B)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_2047B)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_MTU1)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_MTU2)] + \
                                    tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_JUMBO)];
        p_tx_stats_plus->bcast_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_BCAST)];
        p_tx_stats_plus->error_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_FCS_ERROR)];
        p_tx_stats_plus->jumbo_events += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_JUMBO)];
        p_tx_stats_plus->mcast_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_MCAST)];
        p_tx_stats_plus->ucast_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_UCAST)];
        p_tx_stats_plus->underruns_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_MAC_UNDERRUN)];
    }
    else
    {
        ctc_stats_mac_snd_t* p_stats_mac_snd = &p_stats->u.stats_detail.stats.tx_stats;

        p_stats_mac_snd->good_ucast_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_UCAST)];
        p_stats_mac_snd->good_ucast_bytes += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_UCAST)];
        p_stats_mac_snd->good_mcast_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_MCAST)];
        p_stats_mac_snd->good_mcast_bytes += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_MCAST)];
        p_stats_mac_snd->good_bcast_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_BCAST)];
        p_stats_mac_snd->good_bcast_bytes += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_BCAST)];
        p_stats_mac_snd->good_pause_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_PAUSE)];
        p_stats_mac_snd->good_pause_bytes += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_PAUSE)];
        p_stats_mac_snd->good_control_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_CONTROL)];
        p_stats_mac_snd->good_control_bytes += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_CONTROL)];
        p_stats_mac_snd->pkts_63 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_63B)];
        p_stats_mac_snd->bytes_63 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_63B)];
        p_stats_mac_snd->pkts_64 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_64B)];
        p_stats_mac_snd->bytes_64 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_64B)];
        p_stats_mac_snd->pkts_65_to_127 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_127B)];
        p_stats_mac_snd->bytes_65_to_127 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_127B)];
        p_stats_mac_snd->pkts_128_to_255 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_255B)];
        p_stats_mac_snd->bytes_128_to_255 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_255B)];
        p_stats_mac_snd->pkts_256_to_511 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_511B)];
        p_stats_mac_snd->bytes_256_to_511 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_511B)];
        p_stats_mac_snd->pkts_512_to_1023 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_1023B)];
        p_stats_mac_snd->bytes_512_to_1023 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_1023B)];
        p_stats_mac_snd->pkts_1024_to_1518 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_1518B)];
        p_stats_mac_snd->bytes_1024_to_1518 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_1518B)];
        p_stats_mac_snd->pkts_1519_to_2047 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_2047B)];
        p_stats_mac_snd->bytes_1519_to_2047 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_2047B)];
        p_stats_mac_snd->pkts_2048_to_mtu1 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_MTU1)];
        p_stats_mac_snd->bytes_2048_to_mtu1 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_MTU1)];
        p_stats_mac_snd->pkts_mtu1_to_mtu2 += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_MTU2)];
        p_stats_mac_snd->bytes_mtu1_to_mtu2 += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_MTU2)];

        p_stats_mac_snd->jumbo_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_JUMBO)];
        p_stats_mac_snd->jumbo_bytes += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_JUMBO)];
        p_stats_mac_snd->oversize_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_JUMBO)] + \
                                           tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_MTU2)];
        p_stats_mac_snd->oversize_bytes += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_JUMBO)] + \
                                           tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_MTU2)];
        p_stats_mac_snd->mac_underrun_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_MAC_UNDERRUN)];
        p_stats_mac_snd->mac_underrun_bytes += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_MAC_UNDERRUN)];
        p_stats_mac_snd->fcs_error_pkts += tmp_mac_stats.mac_stats_tx_pkts[TX_TYPE(SYS_STATS_MAC_SEND_FCS_ERROR)];
        p_stats_mac_snd->fcs_error_bytes += tmp_mac_stats.mac_stats_tx_bytes[TX_TYPE(SYS_STATS_MAC_SEND_FCS_ERROR)];
        if(DRV_IS_TMG(lchip))
        {
            _sys_usw_mac_stats_get_pfc_stats(lchip, mac_stats_id, mac_id, 1, p_stats);
        }
    }


    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_get_tx_stats(uint8 lchip, uint32 gport, ctc_mac_stats_t* p_stats)
{
    ctc_mac_stats_t* p_tmp_stats = NULL;
    uint8 mac_num = 0;
    uint32 mac_id = 0;
    uint8 client_bind = 1;
    uint32 mac_stats_id = 0;
    uint16 lport = 0;
    uint32 flexe_mac_id = 0;
    uint32 port_type = 0;
    uint8 flexe_aps = 0;
    uint32 speed_mode = 0;
    uint32 if_type = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STATS_DBG_FUNC();
    SYS_STATS_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_stats);
    if (SYS_CB(SYS_CB_TSX_GET_MAC_STATS_EN,lchip))
    {
        SYS_STATS_DBG_ERROR("tsx already controled mac stats\n");
        return CTC_E_IN_USE;
    }
    if (!DRV_FROM_AT(lchip))
    {
        MCHIP_DMA(lchip)->dma_stats_func(lchip, SYS_DMA_PORT_STATS_CHAN_ID);
    }
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);
    dmps_port_info.gport = gport;
    STATS_LOCK();
    CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    if (SYS_DMPS_NETWORK_PORT != port_type && SYS_DMPS_CPU_MAC_PORT != port_type && SYS_DMPS_CPUMAC_NETWORK_PORT != port_type)
    {
        STATS_UNLOCK();
        return CTC_E_INVALID_CONFIG;
    }
    CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, &speed_mode));
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_IF_TYPE, &if_type));
    }
    if (p_stats->p_next)
    {
        sys_usw_dmps_get_flexe_aps(lchip, lport, &flexe_aps, &flexe_mac_id);
        client_bind = flexe_aps?2:1;
    }
    do
    {
        client_bind--;
        SYS_MAC_STATS_GET_RAM_NUM(lchip, mac_num, speed_mode, if_type);
        if (1 == client_bind)
        {
            mac_id = flexe_mac_id;
            mac_stats_id = flexe_mac_id;
            p_tmp_stats = p_stats->p_next;
        }
        else
        {
            CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &mac_id));
            CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_STATS_ID, (void *)&mac_stats_id));
            p_tmp_stats = p_stats;
        }
        sal_memset(&p_tmp_stats->u, 0, sizeof(p_tmp_stats->u));
        do
        {
            CTC_ERROR_RETURN_UNLOCK(_sys_usw_mac_stats_get_tx_stats(lchip, mac_stats_id, mac_id, p_tmp_stats));
            mac_num--;
            if (DRV_FROM_AT(lchip))
            {
                mac_stats_id++;
                mac_id++;
            }
            else
            {
                mac_stats_id += SYS_USW_400G_MAC_ID_OFFSET;
                mac_id += SYS_USW_400G_MAC_ID_OFFSET;
            }
        }
        while (0 < mac_num);
    }while(0 < client_bind);
    STATS_UNLOCK();

    return CTC_E_NONE;
}

int32
_sys_usw_mac_stats_clear_tx_stats(uint8 lchip, uint16 mac_stats_id, uint16 mac_id)
{

    uint16  base = 0;
    uint16 index = 0;
    uint32 cmd = 0;
    uint32 tbl_id = 0;
    uint32 tbl_id_base = DRV_FROM_TMM(lchip) ? McMacStatsRam0_t : QuadSgmacStatsRam0_t;
    ds_t qmac_stats_ram;
    uint32 ram_idx = 0;
    uint8  is_cpumac = 0;

    sal_memset(&qmac_stats_ram, 0, sizeof(ds_t));
    CTC_ERROR_RETURN(_sys_usw_mac_stats_get_stats_tbl_info(lchip, mac_stats_id, &tbl_id, &base));

    if (MCHIP_MAC_STATS(lchip)->stats_clear_mac_stats)
    {
        CTC_ERROR_RETURN(MCHIP_MAC_STATS(lchip)->stats_clear_mac_stats(lchip, tbl_id, base, CTC_STATS_MAC_STATS_TX));/*lchip is base*/
        return CTC_E_NONE;
    }
    
    ram_idx = tbl_id - tbl_id_base;
    if (CTC_STATS_QUERY_MODE_IO == usw_mac_stats_master[lchip]->query_mode)
    {
#if (0 == SDK_WORK_PLATFORM)
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
#else
        /* for uml, add this code to support clear after read */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
#endif
        for (index = SYS_STATS_MAC_SEND_UCAST + base; index < SYS_STATS_MAC_STATS_TYPE_NUM + base; index++)
        {
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &qmac_stats_ram));
        }
    }
    if (DRV_FROM_AT(lchip))
    {
        return CTC_E_NONE;
    }
    if(DRV_FROM_TMM(lchip))
    {
        ram_idx = mac_id/4;
        if (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX)
        {
            is_cpumac = 1;
        }
    }

    if (is_cpumac)
    {
        sal_memset(&usw_mac_stats_master[lchip]->cpumac_stats[mac_id - SYS_CPU_MAC_ID_MIN].mac_stats_tx[0], 0, sizeof(sys_mac_stats_tx_t));
    }
    else
    {
        sal_memset(&usw_mac_stats_master[lchip]->qmac_stats_table[ram_idx].mac_stats_tx[mac_id % 4], 0, sizeof(sys_mac_stats_tx_t));
    }

    if(DRV_IS_TMG(lchip))
    {
        _sys_usw_mac_stats_get_pfc_stats(lchip, mac_stats_id, mac_id, 1, NULL);
        sal_memset(&usw_mac_stats_master[lchip]->qmgc_pfc_stats_table[mac_id].mac_stats_tx, 0, sizeof(uint64)*8);
    }

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_clear_tx_stats(uint8 lchip, uint32 gport)
{
    uint32 mac_id = 0;
    uint8 mac_num = 0;
    uint16 lport = 0;
    uint8 client_bind = 1;
    uint32 mac_stats_id = 0;
    uint32 flexe_mac_id = 0;
    uint32 port_type = 0;
    uint8 flexe_aps = 0;
    uint32 speed_mode = 0;
    uint32 if_type = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    SYS_STATS_DBG_FUNC();
    SYS_STATS_INIT_CHECK();

    if (!DRV_FROM_AT(lchip))
    {
        MCHIP_DMA(lchip)->dma_stats_func(lchip, SYS_DMA_PORT_STATS_CHAN_ID);
    }
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);
    dmps_port_info.gport = gport;
    STATS_LOCK();
    CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, (void*)&mac_id));
    CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    if (SYS_DMPS_NETWORK_PORT != port_type && SYS_DMPS_CPU_MAC_PORT != port_type && SYS_DMPS_CPUMAC_NETWORK_PORT != port_type)
    {
        STATS_UNLOCK();
        return CTC_E_INVALID_CONFIG;
    }
    CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, &speed_mode));
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_IF_TYPE, &if_type));
    }
    sys_usw_dmps_get_flexe_aps(lchip, lport, &flexe_aps, &flexe_mac_id);
    client_bind = flexe_aps?2:1;

    do
    {
        client_bind--;
    	SYS_MAC_STATS_GET_RAM_NUM(lchip, mac_num, speed_mode, if_type);
        if (1 == client_bind)
        {
            mac_stats_id = flexe_mac_id;
            mac_id = flexe_mac_id;
        }
        else
        {
            CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_STATS_ID, (void *)&mac_stats_id));
            CTC_ERROR_RETURN_UNLOCK(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &mac_id));
        }
        do
        {
            CTC_ERROR_RETURN_UNLOCK(_sys_usw_mac_stats_clear_tx_stats(lchip, mac_stats_id, mac_id));
			if (DRV_FROM_AT(lchip))
			{
				mac_stats_id++;
				mac_id++;
			}
			else
			{
	            mac_stats_id += SYS_USW_400G_MAC_ID_OFFSET;
	            mac_id += SYS_USW_400G_MAC_ID_OFFSET;
            }
			mac_num--;
        }while(0 < mac_num);
    }while(0 < client_bind);
    STATS_UNLOCK();

    return CTC_E_NONE;
}

void
sys_usw_mac_stats_get_port_rate(uint8 lchip, uint32 gport, uint64* p_rate)
{

    int32       ret = CTC_E_NONE;
    uint32      enable = 0;
    uint64      pre_throughput[2] = {0};
    uint64      cur_throughput[2] = {0};
    uint64      intv = 0;
    sal_systime_t  pre_timestamp;
    sal_systime_t  cur_timestamp;

    sal_memset(&pre_timestamp,  0, sizeof(sal_systime_t));
    sal_memset(&cur_timestamp,  0, sizeof(sal_systime_t));

    STATS_LOCK();

    p_rate[CTC_STATS_MAC_STATS_RX] = 0;
    p_rate[CTC_STATS_MAC_STATS_TX] = 0;

    ret = _sys_usw_mac_stats_get_throughput(lchip, gport, pre_throughput, &pre_timestamp);

    ret = ret ? ret : _sys_usw_mac_stats_sync_throughput(lchip, gport, NULL);

    ret = ret ? ret : _sys_usw_mac_stats_get_throughput(lchip, gport, cur_throughput, &cur_timestamp);

    ret = ret ? ret : sys_usw_port_api_get_property(lchip, gport, CTC_PORT_PROP_MAC_EN, &enable);

    intv = (((uint64)cur_timestamp.tv_sec * 1000000 + cur_timestamp.tv_usec) - ((uint64)pre_timestamp.tv_sec * 1000000 + pre_timestamp.tv_usec)) / 1000;

    if ((CTC_E_NONE != ret) || (0 == enable) || (0 == intv))
    {
        SYS_STATS_DBG_INFO("%s %d, ret:%d, enable:%u, intv:%"PRIu64" ms.\n", __FUNCTION__, __LINE__, ret, enable, intv);
        STATS_UNLOCK();
        return;
    }

    p_rate[CTC_STATS_MAC_STATS_RX] = ((cur_throughput[CTC_STATS_MAC_STATS_RX] - pre_throughput[CTC_STATS_MAC_STATS_RX])
                                      / intv) * 1000;
    p_rate[CTC_STATS_MAC_STATS_TX] = ((cur_throughput[CTC_STATS_MAC_STATS_TX] - pre_throughput[CTC_STATS_MAC_STATS_TX])
                                      / intv) * 1000;
    SYS_STATS_DBG_INFO("%s gport:0x%04X, time-interval:%"PRIu64" ms.\n", __FUNCTION__, gport, intv);

    STATS_UNLOCK();
    return;
}

int32
sys_usw_mac_stats_show_status(uint8 lchip)
{
    SYS_STATS_INIT_CHECK();

    SYS_STATS_DBG_DUMP("\n");
    SYS_STATS_DBG_DUMP("--------------------------Mac stats status-------------------------\n");

    STATS_LOCK();
    SYS_STATS_DBG_DUMP("%-30s:%10s \n", "Mac stats mode", usw_mac_stats_master[lchip]->stats_mode?"sdk config":"user config");
    SYS_STATS_DBG_DUMP("%-30s:%10s \n", "Query mode", usw_mac_stats_master[lchip]->query_mode?"poll":"io");
    SYS_STATS_DBG_DUMP("%-30s:%10s \n", "Store mode", usw_mac_stats_master[lchip]->store_mode?"software":"hardware");
    SYS_STATS_DBG_DUMP("%-30s:%10u \n", "Poll timer", usw_mac_stats_master[lchip]->mac_timer);
    STATS_UNLOCK();

    SYS_STATS_DBG_DUMP("------------------------------------------------------------------\n");
    SYS_STATS_DBG_DUMP("\n");

    return CTC_E_NONE;
}

int32
sys_usw_mac_stats_dump_db(uint8 lchip, sal_file_t p_f,ctc_global_dump_db_t* p_dump_param)
{
    int32 ret = CTC_E_NONE;

    SYS_STATS_INIT_CHECK();
    STATS_LOCK();
    SYS_DUMP_DB_LOG(p_f, "%s\n", "# MAC STATS");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "{");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "Master config:");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "---------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-30s:%10s \n", "Mac stats mode", usw_mac_stats_master[lchip]->stats_mode?"sdk config":"user config");
    SYS_DUMP_DB_LOG(p_f, "%-30s:%10s \n", "Query mode", usw_mac_stats_master[lchip]->query_mode?"poll":"io");
    SYS_DUMP_DB_LOG(p_f, "%-30s:%10s \n", "Store mode", usw_mac_stats_master[lchip]->store_mode?"software":"hardware");
    SYS_DUMP_DB_LOG(p_f, "%-30s:%10u \n", "Poll timer", usw_mac_stats_master[lchip]->mac_timer);
    SYS_DUMP_DB_LOG(p_f, "%s\n", "---------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "}");

    STATS_UNLOCK();

    return ret;
}

#define ___________MAC_STATS_INIT________________________

int32
sys_usw_mac_stats_init(uint8 lchip, ctc_stats_global_cfg_t* stats_global_cfg)
{
    int32 ret = 0;
    uint32 cmd = 0;
    uint32 dma_timer = 0;
    tbls_id_t tblid = MaxTblId_t;
    ds_t stats_cfg_tbl;
    uint8 i = 0;
    uint8 instance = 0;
    uint32 start_tbl = 0;
    uint32 end_tbl = 0;
    QuadSgmacStatsCfg_m QuadSgmacCfg;
#if (SDB_MEM_MODEL == SDB_MODE)
    return CTC_E_NONE;
#endif

    LCHIP_CHECK(lchip);

    /*init global variable*/
    if (NULL != usw_mac_stats_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT_GLOBAL(lchip, usw_mac_stats_master);

    usw_mac_stats_master[lchip] = (sys_mac_stats_master_t*)mem_malloc(MEM_STATS_MODULE, sizeof(sys_mac_stats_master_t));
    if (NULL == usw_mac_stats_master[lchip])
    {
        SYS_STATS_DBG_ERROR(" No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error_roll;
    }

    sal_memset(usw_mac_stats_master[lchip], 0, sizeof(sys_mac_stats_master_t));
    if(!DRV_FROM_AT(lchip))
    {
        usw_mac_stats_master[lchip]->qmac_stats_table = mem_malloc(MEM_STATS_MODULE, sizeof(sys_qmac_stats_t)*MCHIP_CAP(SYS_CAP_STATS_XQMAC_RAM_NUM)*MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM) / SYS_STATS_XQMAC_PORT_MAX);
        if (NULL ==   usw_mac_stats_master[lchip]->qmac_stats_table)
        {
            SYS_STATS_DBG_ERROR(" No memory \n");
            ret = CTC_E_NO_MEMORY;
            goto error_roll;
        }
        sal_memset(usw_mac_stats_master[lchip]->qmac_stats_table, 0, sizeof(sys_qmac_stats_t)* MCHIP_CAP(SYS_CAP_STATS_XQMAC_RAM_NUM)*MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM) / SYS_STATS_XQMAC_PORT_MAX);
        if(DRV_IS_TMG(lchip))
        {
            usw_mac_stats_master[lchip]->qmgc_pfc_stats_table = mem_malloc(MEM_STATS_MODULE, sizeof(sys_qmac_pfc_stats_t)*(MCHIP_CAP(SYS_CAP_STATS_XQMAC_RAM_NUM)+1)*MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM));
            if (NULL ==   usw_mac_stats_master[lchip]->qmgc_pfc_stats_table)
            {
                SYS_STATS_DBG_ERROR(" No memory \n");
                ret = CTC_E_NO_MEMORY;
                goto error_roll;
            }
            sal_memset(usw_mac_stats_master[lchip]->qmgc_pfc_stats_table, 0, sizeof(sys_qmac_pfc_stats_t)* (MCHIP_CAP(SYS_CAP_STATS_XQMAC_RAM_NUM)+1)*MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM));
        }
    }
    sal_mutex_create(&(usw_mac_stats_master[lchip]->p_stats_mutex));
    usw_mac_stats_master[lchip]->store_mode = SYS_MAC_STATS_STORE_SW;   /* default store in software db */
    usw_mac_stats_master[lchip]->stats_mode = (stats_global_cfg->stats_mode) ? CTC_STATS_MODE_DEFINE : CTC_STATS_MODE_USER;
    usw_mac_stats_master[lchip]->query_mode = (stats_global_cfg->query_mode) ? CTC_STATS_QUERY_MODE_POLL : CTC_STATS_QUERY_MODE_IO;

#if defined (EMULATION_ENV) || (1 == SDK_WORK_PLATFORM)
    MCHIP_MAC_STATS(lchip)->stats_get_mac_stats = NULL;
    MCHIP_MAC_STATS(lchip)->stats_sync_throughput = NULL;
    MCHIP_MAC_STATS(lchip)->stats_clear_mac_stats = NULL;
    usw_mac_stats_master[lchip]->store_mode = SYS_MAC_STATS_STORE_HW;
#endif

    sal_memset(&stats_cfg_tbl, 0, sizeof(ds_t));
    if(DRV_IS_TMG(lchip))
    {
        SetQuadSgmacStatsCfg(V, clearOnRead_f,          &stats_cfg_tbl, 1);
        SetQuadSgmacStatsCfg(V, ge64BPktHiPri_f,        &stats_cfg_tbl, 1);
        SetQuadSgmacStatsCfg(V, incrHold_f,             &stats_cfg_tbl, 0);
        SetQuadSgmacStatsCfg(V, incrSaturate_f,         &stats_cfg_tbl, 1);
        SetQuadSgmacStatsCfg(V, packetLenMtu1_f,        &stats_cfg_tbl, 0x1000);
        SetQuadSgmacStatsCfg(V, packetLenMtu2_f,        &stats_cfg_tbl, 0x600);
        SetQuadSgmacStatsCfg(V, statsOverWriteEnable_f, &stats_cfg_tbl, 0);
        SetQuadSgmacStatsCfg(V, maxInitCnt_f, &stats_cfg_tbl, 0);
    }
    else if(DRV_FROM_TMM(lchip))
    {
        SetMcMacStats0Cfg(V, cfgClearOnRead0_f,          &stats_cfg_tbl, 1);
        SetMcMacStats0Cfg(V, cfgGe64BPktHiPri0_f,        &stats_cfg_tbl, 1);
        SetMcMacStats0Cfg(V, cfgIncrHold0_f,             &stats_cfg_tbl, 0);
        SetMcMacStats0Cfg(V, cfgIncrSaturate0_f,         &stats_cfg_tbl, 1);
        SetMcMacStats0Cfg(V, cfgQuadSgmac0PacketLenMtu1_f,        &stats_cfg_tbl, 0x1000);
        SetMcMacStats0Cfg(V, cfgQuadSgmac0PacketLenMtu2_f,        &stats_cfg_tbl, 0x600);
        SetMcMacStats0Cfg(V, cfgStatsOverWriteEnable0_f, &stats_cfg_tbl, 0);
    }
    else
    {
        SetQuadSgmacStatsCfg0(V, clearOnRead_f,          &stats_cfg_tbl, 1);
        SetQuadSgmacStatsCfg0(V, ge64BPktHiPri_f,        &stats_cfg_tbl, 1);
        SetQuadSgmacStatsCfg0(V, incrHold_f,             &stats_cfg_tbl, 0);
        SetQuadSgmacStatsCfg0(V, incrSaturate_f,         &stats_cfg_tbl, 1);
        SetQuadSgmacStatsCfg0(V, packetLenMtu1_f,        &stats_cfg_tbl, 0x1000);
        SetQuadSgmacStatsCfg0(V, packetLenMtu2_f,        &stats_cfg_tbl, 0x600);
        SetQuadSgmacStatsCfg0(V, statsOverWriteEnable_f, &stats_cfg_tbl, 0);
        SetQuadSgmacStatsCfg0(V, maxInitCnt_f, &stats_cfg_tbl, 0);
    }

    SYS_MAC_STATS_GET_TABLE_RANGE(lchip, start_tbl, end_tbl);
    SYS_MAC_STATS_GET_INSTANCE_NUM(lchip, instance);
    for (tblid = start_tbl; tblid <= end_tbl; tblid++)
    {
        for(i = 0; i < instance; i++)
        {
            cmd = DRV_IOW(tblid, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, i, cmd, &stats_cfg_tbl);
        }
    }

    if (DRV_FROM_TMM(lchip))
    {
        i = (DRV_IS_TMG(lchip)?20:0);
        cmd = DRV_IOR(QuadSgmacStatsCfg_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, 0, cmd, &QuadSgmacCfg);
        SetQuadSgmacStatsCfg(V, clearOnRead_f,  &QuadSgmacCfg, 1);
        SetQuadSgmacStatsCfg(V, ge64BPktHiPri_f,  &QuadSgmacCfg, 1);
        SetQuadSgmacStatsCfg(V, incrHold_f,  &QuadSgmacCfg, 0);
        SetQuadSgmacStatsCfg(V, incrSaturate_f,  &QuadSgmacCfg, 1);
        SetQuadSgmacStatsCfg(V, packetLenMtu1_f,  &QuadSgmacCfg, 0x1000);
        SetQuadSgmacStatsCfg(V, packetLenMtu2_f,  &QuadSgmacCfg, 0x600);
        SetQuadSgmacStatsCfg(V, statsOverWriteEnable_f,  &QuadSgmacCfg, 0);
        cmd = DRV_IOW(QuadSgmacStatsCfg_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, i, cmd, &QuadSgmacCfg);
    }
    if(DRV_FROM_AT(lchip))
    {
        usw_mac_stats_master[lchip]->sync_cb = _sys_at_mac_stats_sync_cb_func;
    }
    else
    {
        usw_mac_stats_master[lchip]->sync_cb = _sys_usw_mac_stats_sync_cb_func;
    }
    if (SYS_MAC_STATS_STORE_SW == usw_mac_stats_master[lchip]->store_mode)
    {
        CTC_ERROR_GOTO(sys_usw_dma_register_cb(SYS_CHIP_CONVERT_DMA(lchip), SYS_DMA_CB_TYPE_PORT_STATS, sys_usw_mac_stats_sync_dma_stats), ret, error_roll);/*PP_TODO*/
        dma_timer = ((CTC_STATS_QUERY_MODE_POLL == usw_mac_stats_master[lchip]->query_mode) ? stats_global_cfg->mac_timer: MCHIP_CAP(SYS_CAP_STATS_DMA_IO_TIMER));

        //CTC_VALUE_RANGE_CHECK(dma_timer, 30, 600);

        CTC_ERROR_GOTO(sys_usw_dma_set_mac_stats_timer(SYS_CHIP_CONVERT(lchip), dma_timer*1000), ret, error_roll);
        usw_mac_stats_master[lchip]->mac_timer = stats_global_cfg->mac_timer;
    }
    else
    {
        CTC_ERROR_GOTO(sys_usw_dma_set_mac_stats_timer(lchip, 0), ret, error_roll);
        usw_mac_stats_master[lchip]->mac_timer = 0;
    }

    return CTC_E_NONE;

error_roll:

    if(NULL != usw_mac_stats_master[lchip]->qmac_stats_table)
    {
        mem_free(usw_mac_stats_master[lchip]->qmac_stats_table);
    }

    if (NULL != usw_mac_stats_master[lchip])
    {
        if (usw_mac_stats_master[lchip]->p_stats_mutex)
        {
            sal_mutex_destroy(usw_mac_stats_master[lchip]->p_stats_mutex);
        }

        mem_free(usw_mac_stats_master[lchip]);
        usw_mac_stats_master[lchip] = NULL;
    }

    return ret;
}


int32
sys_usw_mac_stats_deinit(uint8 lchip)
{
    if (NULL == usw_mac_stats_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT_GLOBAL(lchip, usw_mac_stats_master);

    sys_usw_dma_register_cb(lchip, SYS_DMA_CB_TYPE_PORT_STATS, NULL);
    if(NULL != usw_mac_stats_master[lchip]->qmac_stats_table)
    {
        mem_free(usw_mac_stats_master[lchip]->qmac_stats_table);
    }

    if (usw_mac_stats_master[lchip]->p_stats_mutex)
    {
        sal_mutex_destroy(usw_mac_stats_master[lchip]->p_stats_mutex);
    }
    mem_free(usw_mac_stats_master[lchip]);
    usw_mac_stats_master[lchip] = NULL;

    return CTC_E_NONE;
}

